package com.stoa.floatlib.core

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.*
import android.widget.FrameLayout
import android.widget.TextView
import com.blankj.utilcode.util.ScreenUtils
import com.stoa.floatlib.StoaFloat
import com.stoa.floatlib.StoaFloatReal
import com.stoa.floatlib.StoaFloatReal.managerMap
import com.stoa.floatlib.config.FloatIconConfig
import com.stoa.floatlib.constant.StoaFloatConstant
import com.stoa.floatlib.widget.StoaFloatFrameLayout

internal abstract class AbsStoaFloatView : IStoaFloatView,
    TouchProxy.OnTouchEventListener,
    StoaFloatViewManager.StoaViewAttachedListener {
    val viewTag: String

    constructor(viewTag: String) {
        this.viewTag = viewTag
        this.mTag = viewTag
        this.mHandler = Handler(Looper.myLooper()!!)
        this.mTouchProxy = TouchProxy(this)
        this.mOnGlobalLayoutListener = ViewTreeObserver.OnGlobalLayoutListener {
            mRootView?.run {
                mStoaViewWidth = measuredWidth
                mStoaViewHeight = measuredHeight
                mLastStoaViewPosInfo.run {
                    this.stoaViewWidth = mStoaViewWidth
                    this.stoaViewHeight = mStoaViewHeight
                }
            }
        }
        if (!StoaFloatReal.mLastPosInfoMaps.containsKey(viewTag)) {
            mLastStoaViewPosInfo = LastStoaViewPosInfo()
            StoaFloatReal.mLastPosInfoMaps[viewTag] = mLastStoaViewPosInfo
        } else {
            mLastStoaViewPosInfo = StoaFloatReal.mLastPosInfoMaps[viewTag]!!
        }
    }

    private var mTag: String
    private var mode: Int? = null
    private var mBundle: Bundle? = null
    private var mActivity: Activity? = null
    var mHandler: Handler?

    fun getTag() = mTag
    fun setTag(tag: String) {
        mTag = tag
    }

    fun getMode() = mode
    fun setMode(m: Int) {
        mode = m
    }

    fun getBundle() = mBundle
    fun setBundle(bundle: Bundle) {
        mBundle = bundle
    }

    fun getActivity() = mActivity
    fun setActivity(activity: Activity) {
        mActivity = activity
    }

    private var mStoaViewWidth = 0
    private var mStoaViewHeight = 0
    private lateinit var mLastStoaViewPosInfo: LastStoaViewPosInfo
    private var mStoaViewLayoutParams: StoaViewLayoutParams? = null
    private var childView: View? = null
    private var mTouchProxy: TouchProxy

    /**
     * 创建FrameLayout#LayoutParams 内置悬浮窗调用
     */
    var mFrameLayoutParams: FrameLayout.LayoutParams? = null

    /**
     * 创建FrameLayout#LayoutParams 系统悬浮窗调用
     */
    private var mWindowLayoutParams: WindowManager.LayoutParams? = null


    private var mViewTreeObserver: ViewTreeObserver? = null
    private var mOnGlobalLayoutListener: ViewTreeObserver.OnGlobalLayoutListener

    private var mRootView: FrameLayout? = null
    private lateinit var mContext: Context

    fun updateViewLayout(tag: String, isActivityResume: Boolean) {
        if (mRootView == null || childView == null || mFrameLayoutParams == null || !isNormalMode()) {
            return
        }
        if (isActivityResume) {
            if (managerMap.keys.contains(tag)) {
                mFrameLayoutParams?.run {
                    leftMargin = FloatIconConfig.getLastPosX(viewTag)
                    topMargin = FloatIconConfig.getLastPosY(viewTag)
                }
            } else {
                val point =
                    managerMap[tag]?.getStoaFloatViewPos(tag)
                point?.run {
                    mFrameLayoutParams?.leftMargin = x
                    mFrameLayoutParams?.topMargin = y
                }
            }
        } else {
            mLastStoaViewPosInfo.run {
                isPortrait = ScreenUtils.isPortrait()
                mFrameLayoutParams?.let {
                    leftMarginPercent =
                        it.leftMargin.toFloat() / ScreenUtils.getAppScreenWidth().toFloat()
                    topMarginPercent =
                        it.topMargin.toFloat() / ScreenUtils.getAppScreenHeight().toFloat()
                }
            }
        }

        if (managerMap.keys.contains(tag)) {
            mFrameLayoutParams?.width = StoaFloat.FLOAT_SIZE_WIDTH
            mFrameLayoutParams?.height = StoaFloat.FLOAT_SIZE_HEIGHT
        } else {
            mFrameLayoutParams?.width = mStoaViewWidth
            mFrameLayoutParams?.height = mStoaViewHeight
        }

        resetBorderline(mFrameLayoutParams)
        mRootView?.layoutParams = mFrameLayoutParams
    }

    /**
     * 限制边界 调用的时候必须保证是在控件能获取到宽高德前提下
     */
    private fun resetBorderline(normalFrameLayoutParams: FrameLayout.LayoutParams?) {
        //如果是系统模式或者手动关闭动态限制边界
        if (!restrictBorderline() || !isNormalMode() || normalFrameLayoutParams == null) {
            return
        }
        //LogHelper.i(TAG, "topMargin==>" + normalFrameLayoutParams.topMargin + "  leftMargin====>" + normalFrameLayoutParams.leftMargin);
        if (normalFrameLayoutParams.topMargin <= 0) {
            normalFrameLayoutParams.topMargin = 0
        }
        if (ScreenUtils.isPortrait()) {
            if (normalFrameLayoutParams.topMargin >= getScreenLongSideLength() - mStoaViewHeight) {
                normalFrameLayoutParams.topMargin = getScreenLongSideLength() - mStoaViewHeight
            }
        } else {
            if (normalFrameLayoutParams.topMargin >= getScreenShortSideLength() - mStoaViewHeight) {
                normalFrameLayoutParams.topMargin = getScreenShortSideLength() - mStoaViewHeight
            }
        }
        if (normalFrameLayoutParams.leftMargin <= 0) {
            normalFrameLayoutParams.leftMargin = 0
        }
        if (ScreenUtils.isPortrait()) {
            if (normalFrameLayoutParams.leftMargin >= getScreenShortSideLength() - mStoaViewWidth) {
                normalFrameLayoutParams.leftMargin = getScreenShortSideLength() - mStoaViewWidth
            }
        } else {
            if (normalFrameLayoutParams.leftMargin >= getScreenLongSideLength() - mStoaViewWidth) {
                normalFrameLayoutParams.leftMargin = getScreenLongSideLength() - mStoaViewWidth
            }
        }
    }

    /**
     * 是否限制布局边界
     *
     * @return
     */
    open fun restrictBorderline(): Boolean {
        return true
    }

    /**
     * 获取屏幕长边的长度 不包含statusBar
     *
     * @return
     */
    open fun getScreenLongSideLength(): Int {
        return if (ScreenUtils.isPortrait()) {
            //ScreenUtils.getScreenHeight(); 包含statusBar
            //ScreenUtils.getAppScreenHeight(); 不包含statusBar
            ScreenUtils.getAppScreenHeight()
        } else {
            ScreenUtils.getAppScreenWidth()
        }
    }

    /**
     * 获取屏幕短边的长度 不包含statusBar
     *
     * @return
     */
    open fun getScreenShortSideLength(): Int {
        return if (ScreenUtils.isPortrait()) {
            ScreenUtils.getAppScreenWidth()
        } else {
            ScreenUtils.getAppScreenHeight()
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    fun performCreate(context: Context) {
        onCreate(context)
//        if (!StoaFloatConstant.IS_NORMAL_FLOAT_MODE) {
//            StoaFloatViewManager.getInstance(context)
//        }

        mRootView = if (StoaFloatConstant.IS_NORMAL_FLOAT_MODE) {
            StoaFloatFrameLayout(context)
        } else {
            object : StoaFloatFrameLayout(context) {
                override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
                    event?.action?.takeIf { it == KeyEvent.KEYCODE_BACK && shouldDealBackKey() }
                        ?.apply {
                            //监听返回键
                            if (event.keyCode == KeyEvent.KEYCODE_BACK || event.keyCode == KeyEvent.KEYCODE_HOME) {
                                return onBackPressed()
                            }
                        }
                    return super.dispatchKeyEvent(event)
                }
            }
        }
        mContext = mRootView!!.context

        addViewTreeObserverListener()
        childView = onCreateView(context, mRootView, viewTag)
        mRootView?.run {
            val tv = TextView(mContext)
            tv.text = viewTag
            addView(tv)
            addView(childView)
            onViewCreated(this)
            setOnTouchListener { v, event ->
                if (rootView != null) {
                    mTouchProxy.onTouchEvent(v!!, event!!)
                } else {
                    false
                }
            }
        }
        mStoaViewLayoutParams = StoaViewLayoutParams()
        if (StoaFloatConstant.IS_NORMAL_FLOAT_MODE) {
            mFrameLayoutParams = FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.WRAP_CONTENT,
                FrameLayout.LayoutParams.WRAP_CONTENT
            )
            mFrameLayoutParams?.gravity = Gravity.START or Gravity.TOP
            mStoaViewLayoutParams?.gravity = Gravity.START or Gravity.TOP
        } else {
            // TODO: 2020/9/13 系统弹窗
        }
        mStoaViewLayoutParams?.let { initStoaFloatViewLayoutParams(it) }
        if (StoaFloatConstant.IS_NORMAL_FLOAT_MODE) {
            onNormalLayoutParamsCreated(mFrameLayoutParams)
        } else {
            onSystemLayoutParamsCreated(mWindowLayoutParams)
        }
    }

    open fun performDestroy() {
//        if (!isNormalMode()) {
//            getContext().unregisterReceiver(mInnerReceiver)
//        }
        //移除布局监听
        removeViewTreeObserverListener()
        mHandler = null
        mRootView = null
        onDestroy()
    }

    private fun onSystemLayoutParamsCreated(mWindowLayoutParams: WindowManager.LayoutParams?) {

    }

    private fun addViewTreeObserverListener() {
        mRootView?.takeIf { mViewTreeObserver == null }?.apply {
            mViewTreeObserver = this.viewTreeObserver
            mViewTreeObserver?.addOnGlobalLayoutListener(mOnGlobalLayoutListener)
        }
    }

    private fun removeViewTreeObserverListener() {
        mViewTreeObserver?.takeIf { it.isAlive }?.apply {
            this.removeOnGlobalLayoutListener(mOnGlobalLayoutListener)
        }
    }

    /**
     * 确定普通浮标的初始位置
     * LayoutParams创建完以后调用
     * 调用时建议放在实现下方
     *
     * @param params
     */
    private fun onNormalLayoutParamsCreated(params: FrameLayout.LayoutParams?) {
        //如果有上一个页面的位置记录 这更新位置
        mStoaViewLayoutParams?.run {
            params?.width = width
            params?.height = height
            params?.gravity = gravity
        }
        portraitOrLandscape(params)
    }

    private fun portraitOrLandscape(params: FrameLayout.LayoutParams?) {
        if (params == null) {
            return
        }
        mRootView?.context?.run {
            val point = StoaFloatReal.managerMap[viewTag]?.getStoaFloatViewPos(mTag!!)
            if (point != null) {
                if (ScreenUtils.isPortrait()) {
                    mLastStoaViewPosInfo.run {
                        if (isPortrait) {
                            params.leftMargin = point.x
                            params.topMargin = point.y
                        } else {
                            params.leftMargin = (point.x * leftMarginPercent).toInt()
                            params.topMargin = (point.y * topMarginPercent).toInt()
                        }
                    }
                } else {
                    mLastStoaViewPosInfo.run {
                        if (isPortrait) {
                            params.leftMargin = (point.x * leftMarginPercent).toInt()
                            params.topMargin = (point.y * topMarginPercent).toInt()
                        } else {
                            params.leftMargin = point.x
                            params.topMargin = point.y
                        }
                    }
                }
            } else {
                if (ScreenUtils.isPortrait()) {
                    mLastStoaViewPosInfo.run {
                        mStoaViewLayoutParams?.let {
                            if (isPortrait) {
                                params.leftMargin = it.x!!
                                params.topMargin = it.y!!
                            } else {
                                params.leftMargin = (leftMarginPercent * it.x!!).toInt()
                                params.topMargin = (topMarginPercent * it.y!!).toInt()
                            }
                        }
                    }
                } else {
                    mLastStoaViewPosInfo.run {
                        mStoaViewLayoutParams?.let {
                            if (isPortrait) {
                                params.leftMargin = (leftMarginPercent * it.x!!).toInt()
                                params.topMargin = (topMarginPercent * it.y!!).toInt()
                            } else {
                                params.leftMargin = it.x!!
                                params.topMargin = it.y!!
                            }
                        }
                    }
                }
                mLastStoaViewPosInfo.run {
                    isPortrait = ScreenUtils.isPortrait()
                    leftMarginPercent =
                        params.leftMargin.toFloat() / ScreenUtils.getAppScreenWidth().toFloat()
                    topMarginPercent =
                        params.topMargin.toFloat() / ScreenUtils.getAppScreenHeight().toFloat()
                }

            }
        }
    }

    override fun onDestroy() {
        if (!isNormalMode()) {
            managerMap[viewTag]?.removeStoaViewAttachedListener(this)
        }
    }

    override fun canDrag(): Boolean = true
    override fun onBackPressed(): Boolean = false
    override fun shouldDealBackKey(): Boolean = false
    override fun onEnterBackground() {
        if (!StoaFloatConstant.IS_NORMAL_FLOAT_MODE) {
            mRootView?.visibility = View.GONE
        }
    }

    override fun onEnterForeground() {
        if (!StoaFloatConstant.IS_NORMAL_FLOAT_MODE) {
            mRootView?.visibility = View.VISIBLE
        }
    }

    override fun onMove(x: Int, y: Int, dx: Int, dy: Int) {
        if (!canDrag()) {
            return
        }
        if (isNormalMode()) {
            mFrameLayoutParams?.run {
                leftMargin += dx
                topMargin += dy
            }
            updateViewLayout(mTag, false)
        } else {
            mWindowLayoutParams?.run {
                this.x += dx
                this.y += dy
                //mWindowManager.updateViewLayout(mRootView, mWindowLayoutParams);
            }
        }
    }

    override fun onUp(x: Int, y: Int) {
        if (!canDrag()) {
            return
        }
        if (isNormalMode()) {
            FloatIconConfig.saveLastPosX(viewTag, mFrameLayoutParams?.leftMargin!!)
            FloatIconConfig.saveLastPosY(viewTag, mFrameLayoutParams?.topMargin!!)
        } else {
            FloatIconConfig.saveLastPosX(viewTag, mWindowLayoutParams?.x!!)
            FloatIconConfig.saveLastPosY(viewTag, mWindowLayoutParams?.y!!)
        }
    }

    override fun onDown(x: Int, y: Int) {
        if (!canDrag()) {
            return
        }
    }

    fun isNormalMode(): Boolean {
        return StoaFloatConstant.IS_NORMAL_FLOAT_MODE
    }

    override fun onStoaViewAdd(stoaView: AbsStoaFloatView) {

    }

    /**
     * 强制刷新
     */
    open fun invalidate() {
        mRootView?.takeIf { mFrameLayoutParams != null }.let {
            it!!.layoutParams = mFrameLayoutParams
        }
    }

    fun getRootView() = mRootView

    fun getNormalLayoutParams() = mFrameLayoutParams

    fun postDelayed(runnable: Runnable, i: Long) {
        mHandler?.postDelayed(runnable, i)
    }
}